home *** CD-ROM | disk | FTP | other *** search
- ;----------------------------------------------------------------------
- ; CAPTURE is a resident utility which copies an 80x25 screen buffer
- ; to a file. Activate CAPTURE by pressing ALT-C or any other hot
- ; key combination defined by the symbols HOTKEY and SHIFT_MASK.
- ; The filename will be SCREEN.n. The extension begins with .000 and
- ; is incremented by one each time CAPTURE is activated.
- ;-----------------------------------------------------------------------
- ; BIOS_SEG is located in the ROM-BIOS data area
- ;-----------------------------------------------------------------------
- BIOS_SEG SEGMENT AT 0040H
-
- ORG 0017H
- KB_FLAG DB ? ;BIOS keyboard shift status
- ORG 004AH
- CRT_COLS DB ? ;Current number of screen columns
- ORG 0050H
- CURSOR_POSN DW 8 DUP(?) ;Current cursor location
- ORG 0062H
- ACTIVE_PAGE DB ? ;Active page for CGA and EGA
-
- BIOS_SEG ENDS
-
- ;=======================================================================
- CSEG SEGMENT
- ASSUME CS:CSEG, DS:CSEG, ES:CSEG
- ORG 0100H ;Beginning for .COM programs
- START: JMP INITIALIZE ;Initialization code is at end
-
- ;-----------------------------------------------------------------------
- ; Data needed by this program
- ;-----------------------------------------------------------------------
- HOTKEY EQU 2EH ;Scan code for "C" key
- SHIFT_MASK EQU 00001000B ;Mask for ALT key held down
-
- COPYRIGHT DB "CAPTURE 1.0 (c) 1987 Ziff Communications Co"
- DB 13,10,"Hotkey is ALT-C$",1Ah
- PROGRAMMER DB "Tom Kihlken"
- INSTALLED_MSG DB 13,10,"Already Installed$"
- FILENAME DB "SCREEN.000",0 ;The first filename
- OLDINT09 DD ? ;Old hardware keyboard interrupt vector
- OLDINT13 DD ? ;Old BIOS disk IO interrupt vector
- OLDINT16 DD ? ;Old keyboard input interrupt vector
- OLDINT21 DD ? ;Old DOS function interrupt vector
- WRIT_FILE DB 0 ;If=1, need to write to disk
- ACTIVE DB 0 ;Indicated CAPTURE is in use
- DOS_STAT DB 0 ;Current DOS function indicator
- BUSY_FLAGS DB 0 ;Bit masked as follows:
- ; 1 - DOS function is active
- ; 2 - BIOS disk IO is active
-
- ;-----------------------------------------------------------------------
- ; CAPTURE reads the screen and stores it in an internal buffer.
- ;-----------------------------------------------------------------------
- CAPTURE PROC NEAR
- ASSUME DS:CSEG, ES:BIOS_SEG
-
- CALL GET_CURS_ADDR ;Cursor addr for this page
- PUSH ES:[BX] ;Save the cursor location
- MOV DI,OFFSET BUFFER ;DS:DI points to the buffer
- XOR DX,DX ;Start at row 0, column 0
- READ_LOOP:
- CMP DL,CRT_COLS ;Past right edge of screen?
- JL NOT_PAST_EDGE ;If screen is less than 80
- MOV AX,0720H ;columns, then pad with a blank
- JMP SHORT BUFF_CHAR
- NOT_PAST_EDGE:
- CALL GET_CURS_ADDR ;Get address of BIOS cursor
- MOV ES:[BX],DX ;Tell BIOS where the cursor is
- MOV BH,ACTIVE_PAGE ;Get active page from BIOS data
- MOV AH,8 ;BIOS function to read character
- INT 10H ;Read the character/attribute
- BUFF_CHAR:
- MOV [DI],AX ;Put the character in buffer
- INC DI ;Increment the pointer twice
- INC DI ;Since we stored a word
-
- INC DL ;Do the next char in same row
- CMP DL,80 ;At the right border yet?
- JL READ_LOOP ;Do 80 characters in this row
- INC DH ;Move to next row
- XOR DL,DL ;Back to left edge (Column 0)
- CMP DH,25 ;Done all 25 rows yet?
- JL READ_LOOP ;Loop until whole screen is read
- CALL GET_CURS_ADDR ;Cursor address for this page
- POP ES:[BX] ;Recover the cursor position
- RET ;Then were finished
- CAPTURE ENDP
-
- ;-----------------------------------------------------------------------
- ; This procedure obtains the address of the cursor position for this page
- ;-----------------------------------------------------------------------
- GET_CURS_ADDR PROC NEAR
- ASSUME DS:CSEG, ES:BIOS_SEG
-
- MOV BL,ACTIVE_PAGE ;Get the current page number
- XOR BH,BH ;Convert to a word offset
- SHL BX,1 ;Times two for a word
- ADD BX,OFFSET CURSOR_POSN ;Add base cursor address
- RET
-
- GET_CURS_ADDR ENDP
-
- ;-----------------------------------------------------------------------
- ; This copies the buffer contents to a file. It should only be called
- ; when DOS is in a stable and reentrant condition.
- ;-----------------------------------------------------------------------
- WRITE_TO_FILE PROC NEAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- MOV WRIT_FILE,0 ;Turn off request flag
- STI ;Get interrupts back on
- PUSH AX ;Must preserve all registers
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH BP
- PUSH DS
- PUSH ES
- PUSH CS
- POP DS
- ASSUME DS:CSEG ;DS points to out code segment
- MOV AX,3524H ;Get DOS critical error vector
- CALL DOS_FUNCTION ;Do the DOS function
- PUSH BX ;Save old INT 24 vector on stack
- PUSH ES
-
- ; Replace the DOS severe error interrupt with out own routine.
-
- MOV DX,OFFSET NEWINT24
- MOV AX,2524H ;Setup to change INT 24h vector
- CALL DOS_FUNCTION ;DOS function to change vector
-
- ; Try to open the file to determine if it already exists. If it does,
- ; then just close it and increment the filename.
-
- OPEN_FILE: MOV DX,OFFSET FILENAME ;DS:DX points to filename
- MOV AX,3D00H ;Opin file for read access
- CALL DOS_FUNCTION ;Do the DOS function
- JC OPEN_ERROR ;If open error, take jump
- MOV BX,AX ;Need the handle in BX
- MOV AH,3EH ;Close this file
- CALL DOS_FUNCTION ;Do the DOS function
- CALL INC_FILENAME ;Try the next filename
- JMP OPEN_FILE
- OPEN_ERROR:
- CMP AX,2 ;Was it file not found error?
- JNE DOS_ERR_EXIT ;Exit on any other error
-
- ; Now create the file, then write buffer contents and close it.
-
- MOV DX,OFFSET FILENAME ;DS:DX points to filename
- MOV CX,0020H ;Attribute for new file
- MOV AH,3CH ;Create file for writing
- CALL DOS_FUNCTION ;Do the DOS function
- JC CLOSE_FILE ;On any error, take jump
-
- MOV BX,AX ;Save handle in BX
- MOV DX,OFFSET BUFFER ;Point to output buffer
- MOV CX,4000 ;Write 4000 bytes
- MOV AH,40H ;DOS write to a device function
- CALL DOS_FUNCTION ;Do the DOS function
- CLOSE_FILE:
- MOV AH,3EH ;DOS function to close the file
- CALL DOS_FUNCTION ;Do the DOS function
- CALL INC_FILENAME ;Move to next filename
-
- DOS_ERR_EXIT: POP DS ;Get INT 24H vector from stack
- ASSUME DS:NOTHING
- POP DX
- MOV AX,2524H ;Restore critical error vector
- CALL DOS_FUNCTION ;Do the DOS function
-
- POP ES ;Finally restore all registers
- POP DS
- POP BP
- POP DX
- POP CX
- POP BX
- POP AX
- MOV ACTIVE,0 ;CAPTURE is done now
- RET ;Finished writing to disk
-
- WRITE_TO_FILE ENDP
-
- ;-----------------------------------------------------------------------
- ; This routine does a dos function by calling the old interrupt vector
- ;-----------------------------------------------------------------------
- ASSUME DS:NOTHING, ES:NOTHING
- DOS_FUNCTION PROC NEAR
-
- PUSHF ;These instructions simulate
- CLI ;an interrupt
- CALL CS:OLDINT21 ;Do the DOS function
- STI
- RET
-
- DOS_FUNCTION ENDP
-
- ;-----------------------------------------------------------------------
- ; This procedure increments the extension for the filename.
- ;-----------------------------------------------------------------------
- INC_FILENAME PROC NEAR
- MOV BX,OFFSET FILENAME+9 ;Point to last letter
- INC_NEXT_CHAR:
- INC BYTE PTR [BX] ;Increment the extension
- CMP BYTE PTR [BX],"9" ;Check for carry
- JLE INC_RETURN ;If none, were finished
- MOV BYTE PTR [BX],"0" ;Set this digit to zero
- DEC BX ;Backup to next digit
- CMP BX,OFFSET FILENAME+6 ;Dont increment the dot
- JLE INC_RETURN
- JMP INC_NEXT_CHAR
- INC_RETURN:
- RET
- INC_FILENAME ENDP
-
- ;-----------------------------------------------------------------------
- ; Interrupt 09 (Keyboard) Watch for trigger key. When found, ignore
- ; it and execute the CAPTURE routine.
- ;-----------------------------------------------------------------------
- NEWINT09 PROC FAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- STI ;Allow other interrupts
- PUSH AX ;Must save processor state
- IN AL,60H ;Get the scan code
- CMP AL,HOTKEY ;Is it the hot key?
- JE TRIGGER ;If yes, check the mask
- INT09_EXIT: POP AX ;Restore the processor state
- JMP CS:OLDINT09 ;Continue with ROM routine
- TRIGGER:
- PUSH DS ;Preserve DS register
- MOV AX,BIOS_SEG ;Get BIOS data segment
- MOV DS,AX ;Put it in a segment register
- ASSUME DS:BIOS_SEG
- MOV AL,KB_FLAG ;Shift flags
- AND AL,0FH ; only
- CMP AL,SHIFT_MASK ;Is the ALT key down?
- POP DS ;Restore DS register
- ASSUME DS:NOTHING
- JNE INT09_EXIT ;If ALT not down, ignore it
-
- ;Reset the keyboard and 8259 interrutp controller
-
- IN AL,61H
- MOV AH,AL
- OR AL,80H ;Reset bit for keyboard
- OUT 61H,AL ;Reset the keyboard
- MOV AL,AH
- JMP SHORT $+2 ;A short delay
- OUT 61H,AL ;Reenable keyboard
- CLI
- MOV AL,20H
- OUT 20H,AL ;Reset interrupt controller
- STI
-
- CMP ACTIVE,0 ;Is CAPTURE already active?
- JNZ SHORT_RET ;If active, then exit
- MOV ACTIVE,1 ;Its active now
-
- PUSH BX ;Must preserve all registers
- PUSH CX
- PUSH DX
- PUSH BP
- PUSH DI
- PUSH DS
- PUSH ES
- PUSH CS
- POP DS ;Set DS to CSEG
- MOV AX,BIOS_SEG ;ES points to BIOS data area
- MOV ES,AX
- ASSUME DS:CSEG, ES:BIOS_SEG ;Assembler directives
- CALL CAPTURE ;Read the screen contents
- MOV WRIT_FILE,1 ;Indicate need to flush buffer
- POP ES ;Restore all registers
- POP DS
- POP DI
- POP BP
- POP DX
- POP CX
- POP BX
- ASSUME DS:NOTHING, ES:NOTHING
- TEST BUSY_FLAGS,011B ;Is DOS or BIOS disk busy?
- JNZ SHORT_RET ;If yes, then we must wait
- CALL WRITE_TO_FILE ;Otherwise, we'll do it now
- SHORT_RET:
- POP AX ;Stack must be restored
- IRET ;Now were all done
-
- NEWINT09 ENDP
-
- ;-----------------------------------------------------------------------
- ; Interrupt 13H (BIOS diskette I/O) Set the busy flag during diskette I/O
- ;-----------------------------------------------------------------------
- NEWINT13 PROC FAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- PUSHF
- OR CS:BUSY_FLAGS,010B ;Set BIOS busy bit
- POPF
- PUSHF ;This simulates an interrupt
- CALL CS:OLDINT13 ;Do the BIOS function
- PUSHF ;Save result flags
- AND BUSY_FLAGS,11111101B ;Clear BIOS busy bit
- POPF ;Get back result flags
- STI ;Must return with interrupts on
- RET 2 ;Return BIOS result flags
-
- NEWINT13 ENDP
-
- ;-----------------------------------------------------------------------
- ; Interrupt 16H (BIOS keyboard interface) Check to see if the buffer
- ; needs to be written.
- ;-----------------------------------------------------------------------
- NEWINT16 PROC FAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- CMP CS:WRIT_FILE,1 ;Anything to write to disk?
- JE CHECK_DOS_STAT ;If yes, see what DOS is doing
- BIOS_KB:
- JMP CS:OLDINT16 ;Just do normal KB routine
- CHECK_DOS_STAT:
- CMP CS:DOS_STAT,0AH ;Doing read string?
- JE BEGIN_NOW ;If yes, its safe to begin
- CMP CS:DOS_STAT,08H ;Doing keybaord input?
- JNE BIOS_KB ;If yes, its safe to begin
- BEGIN_NOW:
- CALL WRITE_TO_FILE ;Write the buffer to disk
- OR CS:BUSY_FLAGS,001B ;Reset DOS busy bit
- JMP CS:BIOS_KB ;Continue with BIOS routine
- NEWINT16 ENDP
-
- ;-----------------------------------------------------------------------
- ; Interrupt 21H (DOS functions) Used to keep track of DOS function calls
- ;-----------------------------------------------------------------------
- NEWINT21 PROC FAR
- ASSUME DS:NOTHING, ES:NOTHING
-
- PUSHF ;Save the flags
- MOV CS:DOS_STAT,AH ;Store the function number
- OR CS:BUSY_FLAGS,001B ;Set DOS busy bit
-
- OR AH,AH ;Doing function zero?
- JZ JUMP_TO_DOS ;If yes, take the jump
- CMP AH,4BH ;Doing EXEC function?
- JE JUMP_TO_DOS ;If yes, take the jump
-
- POPF
- PUSHF
- CALL CS:OLDINT21 ;Do the DOS function
-
- PUSHF ;Ssve the result flags
-
- AND CS:BUSY_FLAGS,11111110B ;Clear DOS busy bit
- CMP CS:WRIT_FILE,1 ;Anything to write to disk?
- JNE NO_WRITE ;If not just return
-
- CALL WRITE_TO_FILE ;Safe to access disk now
- NO_WRITE:
- POPF ;Recover DOS result flags
- STI ;Must return with interrupts on
- RET 2 ;Return with DOS result flags
- JUMP_TO_DOS:
- POPF
- JMP CS:OLDINT21
- NEWINT21 ENDP
-
- ;-----------------------------------------------------------------------
- ; Interrupt 24H (critical DOS error). This interrupt is only in
- ; effect during a write screen. It is required to suppress the
- ; 'Abort, Retry, Ignore' message. All fatal disk errors are ignored.
- ;-----------------------------------------------------------------------
- NEWINT24 PROC FAR
- ASSUME DS:NOTHING, ES:NOTHING
- XOR AL,AL ;Tells DOS to ignore the error
- IRET ;Thats all we do here
-
- NEWINT24 ENDP
-
- ;----------------------------------------------------------------------
- ; This are is overwritten by the dynamic buffers.
- ;----------------------------------------------------------------------
- PC = $
-
- BUFFER = PC
- PC = PC+4000
- LASTBYTE = PC
-
- ;-----------------------------------------------------------------------
- ; Here is the code used to initialize CAPTURE. It is not keep resident.
- ; The buffer is located here and overlays the initialization code.
- ;-----------------------------------------------------------------------
- ASSUME CS:CSEG, DS:CSEG, ES:NOTHING
-
- INITIALIZE PROC NEAR
-
- MOV DX,OFFSET COPYRIGHT
- MOV AH,9 ;DOS display string service
- INT 21H ;Display title message
-
- ; Search for a previously installed copy of CAPTURE
-
- NOT WORD PTR START ;Modify to avoid false match
- XOR BX,BX ;Start search at segment zero
- MOV AX,CS ;Compare to this code segment
- NEXT_SEGMENT:
- INC BX ;Look at next segment
- CMP AX,BX ;Until reaching this code seg
- MOV ES,BX
- JE NOT_INSTALLED
- MOV SI,OFFSET START ;Setup to compare strings
- MOV DI,SI
- MOV CX,16 ;16 bytes must match
- REP CMPSB ;Compare DS:SI to ES:DI
- OR CX,CX ;Did the strings match?
- JNZ NEXT_SEGMENT ;If no match, try next segment
- MOV DX,OFFSET INSTALLED_MSG ;else, exit with error
- MOV AH,9
- INT 21H
- MOV AX,4C01H
- INT 21H
- NOT_INSTALLED:
- MOV AX,3509H ;Get keyboard break vector
- INT 21H
- MOV WORD PTR [OLDINT09], BX ;Save segment
- MOV WORD PTR [OLDINT09+2],ES ;Save offset
- MOV DX, OFFSET NEWINT09
- MOV AX, 2509H
- INT 21H ;DOS function to change vector
-
- MOV AX,3513H ;Get BIOS disk interrupt vector
- INT 21H
- MOV WORD PTR [OLDINT13], BX ;Save the segment
- MOV WORD PTR [OLDINT13+2],ES ;Save the offset
- MOV DX, OFFSET NEWINT13
- MOV AX, 2513H
- INT 21H ;DOS function to change vector
-
- MOV AX,3516H ;Get keyboard input vector
- INT 21H
- MOV WORD PTR [OLDINT16], BX ;Save the segment
- MOV WORD PTR [OLDINT16+2],ES ;Save the offset
- MOV DX, OFFSET NEWINT16
- MOV AX, 2516H
- INT 21H ;DOS function to change vector
-
- MOV AX,3521H ;Get DOS function vector
- INT 21H
- MOV WORD PTR [OLDINT21], BX
- MOV WORD PTR [OLDINT21+2],ES
- MOV DX, OFFSET NEWINT21
- MOV AX, 2521H
- INT 21H ;DOS function to change vector
-
- ;-----------------------------------------------------------------------
- ; Deallocate our copy of the enviornment.
- ; Leave code and space for the buffer resident.
- ;-----------------------------------------------------------------------
-
- MOV AX,DS:[002CH] ;Get segment of enviornment
- MOV ES,AX ;Put it into ES
- MOV AH,49H ;Release allocated memory
- INT 21H
-
- MOV DX,(OFFSET LASTBYTE - OFFSET CSEG + 15)SHR 4
- MOV AX,3100H
- INT 21H
-
- INITIALIZE ENDP
-
- CSEG ENDS
- END START